/*
 * Copyright (C) 2021 HiHope Open Source Organization .
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 *
 * limitations under the License.
 */

#include "aht20.h"
#include <stdio.h>
#include <unistd.h>

#include "ohos_init.h"

#include <stdio.h>
#include "cmsis_os2.h"
#include "ohos_run.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "ssd1306.h"
#include "ssd1306_tests.h"
#include "securec.h"
#include "lwip/sockets.h"
#include "lwip/ip_addr.h"
#include "wifi_device.h"

#include <string.h>

#define GPIO_A GPIO_NUM_4
#define GPIO_B GPIO_NUM_0
#define OLED_I2C_BAUDRATE 400 * 1000
char buffer[128] = {0};
char msg[256] = {0};
char *p;

#define OPEN_WIFI_NAME "test"
#define SERVER_IP "119.91.109.180"
#define SERVER_PORT 8344
#define OD_DELAY_1000 1000
#define OD_DELAY_100 100

#define GPIO_LED_R GPIO_NUM_2
#define GPIO_LED_Y GPIO_NUM_23
#define GPIO_LED_G GPIO_NUM_22
#define GPIO_BUZZ GPIO_NUM_15

int sock = -1;
struct sockaddr_in client_addr;
char recv_data[512] = {0};
int recv_data_len;
char input[] = "cmd=1&uid=4e2a189d769e4511bd5885742aa3edcb&topic=ledtest\r\n";
void led_gpio_init()
{
  // 初始化GPIO
  // 配置为输出
  gpio_config_t gpior = {
      .intr_type = GPIO_INTR_DISABLE,        // 关闭中断
      .mode = GPIO_MODE_OUTPUT,              // 输出模式
      .pin_bit_mask = 1ULL << GPIO_LED_R,    // 16引脚
      .pull_down_en = GPIO_PULLDOWN_DISABLE, // 关闭下拉
      .pull_up_en = GPIO_PULLUP_ENABLE       // 开启上拉
  };

  gpio_config(&gpior);

  // 配置为输出
  gpio_config_t gpiog = {
      .intr_type = GPIO_INTR_DISABLE,        // 关闭中断
      .mode = GPIO_MODE_OUTPUT,              // 输出模式
      .pin_bit_mask = 1ULL << GPIO_LED_Y,    // 16引脚
      .pull_down_en = GPIO_PULLDOWN_DISABLE, // 关闭下拉
      .pull_up_en = GPIO_PULLUP_ENABLE       // 开启上拉
  };

  gpio_config(&gpiog);

  // 配置为输出
  gpio_config_t gpiob = {
      .intr_type = GPIO_INTR_DISABLE,        // 关闭中断
      .mode = GPIO_MODE_OUTPUT,              // 输出模式
      .pin_bit_mask = 1ULL << GPIO_LED_G,    // 16引脚
      .pull_down_en = GPIO_PULLDOWN_DISABLE, // 关闭下拉
      .pull_up_en = GPIO_PULLUP_ENABLE       // 开启上拉
  };

  gpio_config(&gpiob);

  // 配置为输出
  gpio_config_t gpiobuzz = {
      .intr_type = GPIO_INTR_DISABLE,        // 关闭中断
      .mode = GPIO_MODE_OUTPUT,              // 输出模式
      .pin_bit_mask = 1ULL << GPIO_BUZZ,     // 16引脚
      .pull_down_en = GPIO_PULLDOWN_DISABLE, // 关闭下拉
      .pull_up_en = GPIO_PULLUP_ENABLE       // 开启上拉
  };

  gpio_config(&gpiobuzz);

  gpio_set_level(GPIO_BUZZ, 0);
  printf("gpio init ok!\n");
}

/**
 * 汉字字模在线： https://www.23bei.com/tool-223.html
 * 数据排列：从左到右从上到下
 * 取模方式：横向8位左高位
 **/
void TestDrawChinese1(void)
{
  const uint32_t W = 12, H = 12, S = 16;
  /* [字库]：[HZK1212宋体] [数据排列]:从左到右从上到下 [取模方式]:横向8点左高位 [正负反色]:否 [去掉重复后]共9个字符
    [总字符库]："　－ＯＬＥＤ屏案例"*/
  uint8_t fonts[][24] = {
      {
          /*-- ID:0,字符:"　",ASCII编码:A1A1,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:1,字符:"－",ASCII编码:A3AD,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x7F,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:2,字符:"Ｏ",ASCII编码:A3CF,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x1C,
          0x00,
          0x36,
          0x00,
          0x63,
          0x00,
          0x63,
          0x00,
          0x63,
          0x00,
          0x63,
          0x00,
          0x63,
          0x00,
          0x36,
          0x00,
          0x1C,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:3,字符:"Ｌ",ASCII编码:A3CC,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x78,
          0x00,
          0x30,
          0x00,
          0x30,
          0x00,
          0x30,
          0x00,
          0x30,
          0x00,
          0x30,
          0x00,
          0x31,
          0x00,
          0x33,
          0x00,
          0x7F,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:4,字符:"Ｅ",ASCII编码:A3C5,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x7F,
          0x00,
          0x33,
          0x00,
          0x31,
          0x00,
          0x34,
          0x00,
          0x3C,
          0x00,
          0x34,
          0x00,
          0x31,
          0x00,
          0x33,
          0x00,
          0x7F,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:5,字符:"Ｄ",ASCII编码:A3C4,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x00,
          0x00,
          0x7C,
          0x00,
          0x36,
          0x00,
          0x33,
          0x00,
          0x33,
          0x00,
          0x33,
          0x00,
          0x33,
          0x00,
          0x33,
          0x00,
          0x36,
          0x00,
          0x7C,
          0x00,
          0x00,
          0x00,
          0x00,
          0x00,
      },
      {
          /*-- ID:6,字符:"屏",ASCII编码:C6C1,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x7F,
          0xE0,
          0x40,
          0x20,
          0x7F,
          0xE0,
          0x48,
          0x80,
          0x45,
          0x00,
          0x5F,
          0xE0,
          0x44,
          0x80,
          0x7F,
          0xF0,
          0x44,
          0x80,
          0x44,
          0x80,
          0x48,
          0x80,
          0x90,
          0x80,
      },
      {
          /*-- ID:7,字符:"案",ASCII编码:B0B8,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
          0x04,
          0x00,
          0x7F,
          0xF0,
          0xC8,
          0x20,
          0x7F,
          0xF0,
          0x11,
          0x00,
          0x0E,
          0x00,
          0x71,
          0xC0,
          0x04,
          0x00,
          0xFF,
          0xF0,
          0x15,
          0x00,
          0x24,
          0xC0,
          0xC4,
          0x30,
      },
      {/*-- ID:8,字符:"例",ASCII编码:C0FD,对应字:宽x高=12x12,画布:宽W=16 高H=12,共24字节*/
       0x10, 0x10, 0x1F, 0x90, 0x24, 0x50, 0x27, 0x50, 0x69, 0x50, 0xA9, 0x50, 0x35, 0x50, 0x22, 0x50,
       0x22, 0x10, 0x24, 0x10, 0x28, 0x50, 0x30, 0x20}};
  ssd1306_Fill(Black);
  for (size_t i = 0; i < sizeof(fonts) / sizeof(fonts[0]); i++)
  {
    ssd1306_DrawRegion(i * H, 18, W, H, fonts[i], sizeof(fonts[0]), S); // y= 18 居中显示
  }
  ssd1306_UpdateScreen();
  sleep(1);
}

char *extract_msg_value(const char *input)
{
  const char *msg_key = "msg=";
  size_t key_len = strlen(msg_key);
  const char *start_pos;
  const char *end_pos;

  // 查找 msg= 的位置
  start_pos = strstr(input, msg_key);
  if (start_pos == NULL)
  {
    return NULL; // 如果没有找到 msg=，则返回 NULL
  }

  // 移动到 msg= 之后
  start_pos += key_len;

  // 找到下一个 & 或者字符串末尾
  end_pos = strchr(start_pos, '&');
  if (end_pos == NULL)
  {
    // 如果没有找到 &, 则取到字符串末尾
    size_t len = strlen(start_pos);
    char *result = (char *)malloc(len + 1);
    if (result != NULL)
    {
      strncpy(result, start_pos, len);
      result[len] = '\0'; // 确保字符串以 null 结尾
    }
    return result;
  }
  else
  {
    // 复制从 start_pos 到 end_pos 之间的内容
    size_t len = end_pos - start_pos;
    char *result = (char *)malloc(len + 1);
    if (result != NULL)
    {
      strncpy(result, start_pos, len);
      result[len] = '\0'; // 确保字符串以 null 结尾
    }
    return result;
  }
}

void ExampleTestTask(void *arg)
{
  (void)arg;

  i2c_config_t i2c_initer_1 = {
      .clk_flags = 0,            // 选择默认时钟源
      .master.clk_speed = 50000, // 指定速率为100Kbit,最大可以为400Kbit
      .mode = I2C_MODE_MASTER,   // 主机模式
      .scl_io_num = 17,          // 指定SCL的GPIO口
      .scl_pullup_en = true,     // SCL接上拉电阻
      .sda_io_num = 16,          // 指定SDA的GPIO口
      .sda_pullup_en = true,     // SDA接上拉电阻
  };
  if (i2c_param_config(I2C_NUM_0, &i2c_initer_1) == ESP_OK)
  {
    printf("i2c parm config success\r\n");
  }
  else
  {
    printf("config fail\r\n");
  }

  if (i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0) == ESP_OK)
  {
    printf("i2c driver install success\r\n");
  }
  else
  {
    printf("driver fail\r\n");
  }

  usleep(20 * 1000);
  ssd1306_Init();
  ssd1306_Fill(Black);
  ssd1306_SetCursor(0, 10);
  led_gpio_init();
  sg90_gpio_init();

  int sock = -1;
  struct sockaddr_in client_addr;
  char recv_data[512] = {0};
  int recv_data_len;
  WifiConnect(OPEN_WIFI_NAME);
  printf("start wifi_test test\r\n");
  while (1)
  {
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
      printf("Socket error\n");
      osDelay(OD_DELAY_100);
      continue;
    }
    memset_s(&(client_addr), sizeof(client_addr), 0, sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(SERVER_PORT);
    client_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    printf("try connect to server " SERVER_IP " :%d \n", SERVER_PORT);
    if (connect(sock, (struct sockaddr *)&client_addr, sizeof(struct sockaddr)) == -1)
    {
      closesocket(sock);
      osDelay(OD_DELAY_1000);
      continue;
    }
    printf("Connect to tcp server successful!\n");
    write(sock, input, strlen(input));
    while (1)
    {

      recv_data_len = recv(sock, recv_data, 511, 0);
      if (recv_data_len <= 0)
      {
        break;
      }
      else
      {
        // 对字符串进行处理
        char *p = strstr(recv_data, "msg=");
        if (p != NULL)
        {
          p += 4; // 跳过 "msg="

          // 使用 sscanf 提取 msg 后的值，直到遇到换行符或 '&' 结束
          if (sscanf(p, "%s", msg) == 1)
          { // 注意：%[^&] 表示读取直到遇到 '&'
            printf("Extracted msg value: %s\n", msg);
          }
        }
        else
        {
          printf("Failed to find msg parameter\n");
        }
        if (strcmp(msg, "1") == 0)
        {
          gpio_set_level(GPIO_LED_R, 1);
        }
        if (strcmp(msg, "2") == 0)
        {
          gpio_set_level(GPIO_LED_R, 0);
        }
        if (strcmp(msg, "3") == 0)
        {
          gpio_set_level(GPIO_LED_Y, 1);
        }
        if (strcmp(msg, "4") == 0)
        {
          gpio_set_level(GPIO_LED_Y, 0);
        }
        if (strcmp(msg, "5") == 0)
        {
          gpio_set_level(GPIO_LED_G, 1);
        }
        if (strcmp(msg, "6") == 0)
        {
          gpio_set_level(GPIO_LED_G, 0);
        }
        // if (1)
        // {
        //   gpio_set_level(GPIO_LED_R, 0);
        // }
        // if (msg == '3')
        // {
        //   gpio_set_level(GPIO_LED_Y, 1);
        // }
        // if (msg == '4')
        // {
        //   gpio_set_level(GPIO_LED_Y, 0);
        // }
        // if (msg == '5')
        // {
        //   gpio_set_level(GPIO_LED_G, 1);
        // }
        // if (msg == '6')
        // {
        //   gpio_set_level(GPIO_LED_G, 0);
        // }
      }
    }
  }
}

void ExampleTest(void)
{
  osThreadAttr_t attr;

  printf("ExampleTest\r\n");

  attr.name = "ExampleTest";
  attr.attr_bits = 0U;
  attr.cb_mem = NULL;
  attr.cb_size = 0U;
  attr.stack_mem = NULL;
  attr.stack_size = 40960;
  attr.priority = osPriorityNormal;

  if (osThreadNew(ExampleTestTask, NULL, &attr) == NULL)
  {
    printf("[Example Test] Failed to create ExampleTestTask!\n");
  }
}

OHOS_APP_RUN(ExampleTest);
